package gitee.derumin.configurablefireworkexplosion.mixin;

import gitee.derumin.configurablefireworkexplosion.config.ModConfig;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.FlyingItemEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.projectile.FireworkRocketEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtList;
import net.minecraft.network.packet.s2c.play.ExplosionS2CPacket;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(FireworkRocketEntity.class)
public abstract class FireworkRocketEntityMixin extends ProjectileEntity implements FlyingItemEntity {
    @Shadow
    public abstract boolean wasShotAtAngle();
    @Shadow
    public ItemStack getStack() {return null;}

    public FireworkRocketEntityMixin(EntityType<? extends ProjectileEntity> entityType, World world) {
        super(entityType, world);
    }

    @Inject(method = "explode" , at = @At(value = "INVOKE" , target = "Lnet/minecraft/nbt/NbtList;isEmpty()Z") , cancellable = true)
    private void addExplosion(CallbackInfo ci){
        ItemStack itemStack = ((FireworkRocketEntity)(ProjectileEntity)this).getStack();
        NbtCompound nbtCompound = itemStack.isEmpty() ? null : itemStack.getSubNbt("Fireworks");
        NbtList nbtList = nbtCompound != null ? nbtCompound.getList("Explosions", NbtElement.COMPOUND_TYPE) : null;
        ModConfig config = ModConfig.getInstance();
        if (nbtList != null && !nbtList.isEmpty() && (
                (config.isHandLaunchExplosion() && !this.wasShotAtAngle())
                || (config.isCrossbowShotExplosion() && this.wasShotAtAngle())
        )){
            float explodePower = config.getBaseExplosionPower() + nbtList.size() * config.getFireworkStarMultiplier();
            Explosion explosion = new Explosion(this.getWorld(),this, this.getDamageSources().fireworks((FireworkRocketEntity)((ProjectileEntity) this),this.getOwner()),null,this.getX(),this.getY(),this.getZ(),explodePower,config.isCanCreateFire(), config.getDestructionType());
            explosion.collectBlocksAndDamageEntities();
            explosion.affectWorld(this.getWorld().isClient && config.isShowParticles());
            if (!explosion.shouldDestroy()) {
                explosion.clearAffectedBlocks();
            }
            if (this.getWorld() instanceof ServerWorld serverWorld) {
                for (ServerPlayerEntity serverPlayerEntity : serverWorld.getPlayers()) {
                    if (!(serverPlayerEntity.squaredDistanceTo(this.getX(), this.getY(), this.getZ()) < 4096.0))
                        continue;
                    serverPlayerEntity.networkHandler.sendPacket(new ExplosionS2CPacket(this.getX(), this.getY(), this.getZ(), explodePower, explosion.getAffectedBlocks(), explosion.getAffectedPlayers().get(serverPlayerEntity)));
                }
            }
            ci.cancel();
        }
    }

}
